package com.hp.team.bookstore.service.order;

import java.io.InputStream;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.hp.team.bookstore.dbaccess.dao.profile.RoleHibernateDAO;
import com.hp.team.bookstore.dbaccess.dao.profile.UserHibernateDAO;
import com.hp.team.bookstore.model.profile.User;
import com.hp.team.bookstore.service.exception.BadOperationException;
import com.hp.team.bookstore.service.order.common.Operation;
import com.hp.team.bookstore.service.order.common.OrderListOperations;
import com.hp.team.bookstore.service.order.common.Status;

@Service
public abstract class OrderService {

	private OrderListOperations orderListOperations;

	private Operation currentOperation;

	private String operationsFile;

	private Map<String, Set<String>> currentStatusPaths;

	@Autowired
	protected UserHibernateDAO userDAO;

	@Autowired
	protected RoleHibernateDAO roleDAO;

	protected void setOperationsFile(String operationsFile) {
		this.operationsFile = operationsFile;
	}

	protected Operation getCurrentOperation() {
		return currentOperation;
	}

	protected Map<String, Set<String>> getCurrentStatusPaths() {
		return currentStatusPaths;
	}

	protected void readListOperatrions() {

		try {
			InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(operationsFile);
			JAXBContext jaxbContext = JAXBContext.newInstance(OrderListOperations.class);
			Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
			orderListOperations = (OrderListOperations) unmarshaller.unmarshal(inputStream);
		} catch (JAXBException e) {
			e.printStackTrace();
		}
	}

	protected void initOperation(String role, String operation) throws BadOperationException {
		readListOperatrions();

		currentOperation = null;
		for (Operation op : orderListOperations.getOperations()) {
			if (op.getName().equalsIgnoreCase(operation) && op.getRole().equalsIgnoreCase(role)) {
				currentOperation = op;
				break;
			}
		}

		if (currentOperation == null) {
			String message = "The combination of Role [" + role + "] and Operation [" + operation + "] is invalid.";
			throw new BadOperationException(message);

		} else {

			currentStatusPaths = new TreeMap<String, Set<String>>();

			for (Status status : currentOperation.getStatuses()) {
				String key = status.getFrom();
				Set<String> toStatus = currentStatusPaths.keySet().contains(key)
						? currentStatusPaths.get(key)
						: new TreeSet<String>();

				if (status.getTo() != null) {
					toStatus.add(status.getTo());
				}
				currentStatusPaths.put(key, toStatus);
			}

			System.out.println("Status Paths: " + currentStatusPaths);
		}

	}

	@Transactional
	public Set<User> getAllCreators() {
		return new TreeSet<User>(userDAO.findByRole(new User(), getCreatorRoleName()));
	}

	protected abstract String getCreatorRoleName();

}
